home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / CPP / BTREE.ZIP / BNODE.H next >
Encoding:
C/C++ Source or Header  |  1994-11-14  |  8.1 KB  |  427 lines

  1. /*
  2.  *  BNode.h            Balanced Node Class
  3.  *
  4.  * (c) DownEast Technology, Inc., 1994
  5.  * Written by Steve Nutt
  6.  */
  7.  
  8. #if !defined(BNODE_H)
  9. #define BNODE_H
  10.  
  11. #if !defined(__CLASSLIB_STACKS_H)
  12. #include <ClassLib\Stacks.h>
  13. #endif
  14.  
  15. enum TBalance {
  16.     LeftBalance                = -1,
  17.     Balanced                    = 0,
  18.     RightBalance            = 1,
  19.     DoubleLeftBalance        = LeftBalance * 2,
  20.     DoubleRightBalance    = RightBalance * 2,
  21. };
  22.  
  23. /*
  24.  * Template TNodeImp
  25.  * Contains common functionality to manage traversing and balancing nodes.
  26.  */
  27. template <class Alloc> class TNodeImp : public Alloc
  28. {
  29. public:
  30.     typedef TNodeImp TNodeBase;
  31.     typedef TIStackAsVector<TNodeBase*> TChain;
  32.  
  33.     TNodeImp (void) : balance (Balanced)
  34.         {
  35.         left = right = 0;
  36.         }
  37.  
  38.     TNodeImp*& Left (void)
  39.         {
  40.         return left;
  41.         }
  42.  
  43.     TNodeImp*& Right (void)
  44.         {
  45.         return right;
  46.         }
  47.  
  48.     TNodeImp& LeftNode (void) const
  49.         {
  50.         PRECONDITION (left);
  51.         return *left;
  52.         }
  53.  
  54.     TNodeImp& RightNode (void) const
  55.         {
  56.         PRECONDITION (right);
  57.         return *right;
  58.         }
  59.  
  60.     BOOL BalanceAdd (TNodeImp* child, TNodeImp*& head)
  61.         {
  62.         balance = static_cast<TBalance> (balance + ((child == left) ?
  63.             LeftBalance : RightBalance));
  64.         return Balance (head);
  65.         }
  66.  
  67.     BOOL BalanceDetach (TNodeImp* child, TNodeImp*& head)
  68.         {
  69.         balance = static_cast<TBalance> (balance + ((child == right) ?
  70.             LeftBalance : RightBalance));
  71.         return Balance (head);
  72.         }
  73.  
  74.     TBalance& Balance (void)
  75.         {
  76.         return balance;
  77.         }
  78.  
  79.     TNodeImp* WalkLeft (void);
  80.     TNodeImp* WalkRight (void);
  81.     TNodeImp* WalkLeft (TChain&);
  82.     TNodeImp* WalkRight (TChain&);
  83.     void RotateLeft (TNodeImp*&);
  84.     void RotateRight (TNodeImp*&);
  85.     void RotateLeftRight (TNodeImp*&);
  86.     void RotateRightLeft (TNodeImp*&);
  87.     BOOL Balance (TNodeImp*&);
  88.     static TNodeImp* Next (TChain&);
  89.     static TNodeImp* Previous (TChain&);
  90.  
  91. #if __DEBUG > 0
  92. #if defined(_DEBUG_B_TREE_)
  93.     unsigned CheckNode (int&);
  94. #endif
  95. #endif
  96.  
  97. private:
  98.     TNodeImp* left;
  99.     TNodeImp* right;
  100.     TBalance balance;
  101.  
  102.     const TNodeImp& operator = (const TNodeImp& other);
  103.     TNodeImp (const TNodeImp&);
  104. };
  105.  
  106. template <class Alloc>
  107. TNodeImp<Alloc>* TNodeImp<Alloc>::Next (
  108.     TChain& chain)
  109. {
  110.     const TNodeImp* child = 0;
  111.     while (!chain.IsEmpty())
  112.     {
  113.         TNodeImp& node = **chain.Top();
  114.         if (child && node.Left() == child)
  115.             return &node;
  116.  
  117.         if (node.Right() && node.Right() != child)
  118.         {
  119.             chain.Push (&node.Right());
  120.             return node.RightNode().WalkLeft (chain);
  121.         }
  122.         child = &node;
  123.         chain.Pop();
  124.     }
  125.     return 0;
  126. }
  127.  
  128. template <class Alloc>
  129. TNodeImp<Alloc>* TNodeImp<Alloc>::Previous (
  130.     TChain& chain)
  131. {
  132.     const TNodeImp* child = 0;
  133.     while (!chain.IsEmpty())
  134.     {
  135.         TNodeImp& node = **chain.Top();
  136.         if (child && node.Right() == child)
  137.             return &node;
  138.  
  139.         if (node.Left() && node.Left() != child)
  140.         {
  141.             chain.Push (&node.Left());
  142.             return node.LeftNode().WalkRight (chain);
  143.         }
  144.         child = &node;
  145.         chain.Pop();
  146.     }
  147.     return 0;
  148. }
  149.  
  150. template <class Alloc>
  151. TNodeImp<Alloc>* TNodeImp<Alloc>::WalkLeft (void)
  152. {
  153.     TNodeImp* node = this;
  154.     while (node->left)
  155.         node = node->left;
  156.  
  157.     return node;
  158. }
  159.  
  160. template <class Alloc>
  161. TNodeImp<Alloc>* TNodeImp<Alloc>::WalkRight (void)
  162. {
  163.     TNodeImp* node = this;
  164.     while (node->right)
  165.         node = node->right;
  166.  
  167.     return node;
  168. }
  169.  
  170. template <class Alloc>
  171. TNodeImp<Alloc>* TNodeImp<Alloc>::WalkLeft (
  172.     TChain& chain)
  173. {
  174.     TNodeImp* node = this;
  175.     while (node->left)
  176.     {
  177.         chain.Push (&node->left);
  178.         node = node->left;
  179.     }
  180.     return node;
  181. }
  182.  
  183. template <class Alloc>
  184. TNodeImp<Alloc>* TNodeImp<Alloc>::WalkRight (
  185.     TChain& chain)
  186. {
  187.     TNodeImp* node = this;
  188.     while (node->right)
  189.     {
  190.         chain.Push (&node->right);
  191.         node = node->right;
  192.     }
  193.     return node;
  194. }
  195.  
  196. template <class Alloc>
  197. void TNodeImp<Alloc>::RotateLeft (
  198.     TNodeImp*& head)
  199. {
  200.     PRECONDITION (balance == DoubleRightBalance);
  201.     TNodeImp& child = RightNode();
  202.     PRECONDITION (child.balance != LeftBalance);
  203.     right = child.left;
  204.     child.left = this;
  205.     head = &child;
  206.     if (child.balance == RightBalance)
  207.         balance = child.balance = Balanced;
  208.     else    // child.balance == Balanced
  209.     {
  210.         balance = RightBalance;
  211.         child.balance = LeftBalance;
  212.     }
  213. }
  214.  
  215. template <class Alloc>
  216. void TNodeImp<Alloc>::RotateRight (
  217.     TNodeImp*& head)
  218. {
  219.     PRECONDITION (balance == DoubleLeftBalance);
  220.     TNodeImp& child = LeftNode();
  221.     PRECONDITION (child.balance != RightBalance);
  222.     left = child.right;
  223.     child.right = this;
  224.     head = &child;
  225.     if (child.balance == LeftBalance)
  226.         balance = child.balance = Balanced;
  227.     else    // child.balance == Balanced
  228.     {
  229.         balance = LeftBalance;
  230.         child.balance = RightBalance;
  231.     }
  232. }
  233.  
  234. template <class Alloc>
  235. void TNodeImp<Alloc>::RotateLeftRight (
  236.     TNodeImp*& head)
  237. {
  238.     PRECONDITION (balance == DoubleLeftBalance);
  239.     TNodeImp& child = LeftNode();
  240.     PRECONDITION (child.balance == RightBalance);
  241.     TNodeImp& grandchild = child.RightNode();
  242.     child.right = grandchild.left;
  243.     grandchild.left = &child;
  244.     left = grandchild.right;
  245.     grandchild.right = this;
  246.     head = &grandchild;
  247.     balance = child.balance = Balanced;
  248.     if (grandchild.balance == RightBalance)
  249.         child.balance = LeftBalance;
  250.     else if (grandchild.balance == LeftBalance)
  251.         balance = RightBalance;
  252.     grandchild.balance = Balanced;
  253. }
  254.  
  255. template <class Alloc>
  256. void TNodeImp<Alloc>::RotateRightLeft (
  257.     TNodeImp*& head)
  258. {
  259.     PRECONDITION (balance == DoubleRightBalance);
  260.     TNodeImp& child = RightNode();
  261.     PRECONDITION (child.balance == LeftBalance);
  262.     TNodeImp& grandchild = child.LeftNode();
  263.     child.left = grandchild.right;
  264.     grandchild.right = &child;
  265.     right = grandchild.left;
  266.     grandchild.left = this;
  267.     head = &grandchild;
  268.     balance = child.balance = Balanced;
  269.     if (grandchild.balance == LeftBalance)
  270.         child.balance = RightBalance;
  271.     else if (grandchild.balance == RightBalance)
  272.         balance = LeftBalance;
  273.     grandchild.balance = Balanced;
  274. }
  275.  
  276. template <class Alloc>
  277. BOOL TNodeImp<Alloc>::Balance (
  278.     TNodeImp*& head)
  279. {
  280.     if (balance == DoubleRightBalance)
  281.     {
  282.         if (RightNode().balance != LeftBalance)
  283.             RotateLeft (head);
  284.         else
  285.             RotateRightLeft (head);
  286.         return 1;
  287.     }
  288.     if (balance == DoubleLeftBalance)
  289.     {
  290.         if (LeftNode().balance != RightBalance)
  291.             RotateRight (head);
  292.         else
  293.             RotateLeftRight (head);
  294.         return 1;
  295.     }
  296.     return 0;
  297. }
  298.  
  299. #if __DEBUG > 0
  300. #if defined(_DEBUG_B_TREE_)
  301. template <class Alloc>
  302. unsigned TNodeImp<Alloc>::CheckNode (
  303.     int& height)
  304. {
  305.     int leftHeight = 0;
  306.     int rightHeight = 0;
  307.     unsigned cnt = 0;
  308.  
  309.     if (left)
  310.         cnt += LeftNode().CheckNode (leftHeight);
  311.  
  312.     if (right)
  313.         cnt += RightNode().CheckNode (rightHeight);
  314.  
  315.     height = max (leftHeight, rightHeight) +1;
  316.     CHECK (balance >= LeftBalance && balance <= RightBalance);
  317.     CHECK (leftHeight + balance == rightHeight);
  318.     return cnt +1;
  319. }
  320. #endif
  321. #endif
  322.  
  323. /*
  324.  * Template TDNode
  325.  * Contains functionality to manage direct data
  326.  */
  327. template <class T, class Alloc> class TDNode : public TNodeImp <Alloc>
  328. {
  329. public:
  330.     TDNode (void) : TNodeImp<Alloc> ()
  331.         {
  332.         }
  333.  
  334.     TDNode (const T& value) : TNodeImp<Alloc> (), t (value)
  335.         {
  336.         }
  337.  
  338.     const T& Data (void) const
  339.         {
  340.         return t;
  341.         }
  342.  
  343.     T& Data (void)
  344.         {
  345.         return t;
  346.         }
  347.  
  348.     const T* DataPtr (void) const
  349.         {
  350.         return &Data();
  351.         }
  352.  
  353.     T* DataPtr (void)
  354.         {
  355.         return &Data();
  356.         }
  357.  
  358.     int operator == (const TDNode& other) const
  359.         {
  360.         return t == other.t;
  361.         }
  362.  
  363.     int operator < (const TDNode& other) const
  364.         {
  365.         return t < other.t;
  366.         }
  367.  
  368. private:
  369.     T t;
  370.  
  371.     const TDNode& operator = (const TDNode&);
  372.     TDNode (const TDNode&);
  373. };
  374.  
  375. /*
  376.  * Template TINode
  377.  * Contains functionality to manage indirect data
  378.  */
  379. template <class T, class Alloc> class TINode : public TNodeImp <Alloc>
  380. {
  381. public:
  382.     TINode (void) : TNodeImp<Alloc> (), t (0)
  383.         {
  384.         }
  385.  
  386.     TINode (T* value) : TNodeImp<Alloc> (), t (value)
  387.         {
  388.         }
  389.  
  390.     const T* Data (void) const
  391.         {
  392.         return t;
  393.         }
  394.  
  395.     T*& Data (void)
  396.         {
  397.         return t;
  398.         }
  399.  
  400.     const T* DataPtr (void) const
  401.         {
  402.         return Data();
  403.         }
  404.  
  405.     T* DataPtr (void)
  406.         {
  407.         return Data();
  408.         }
  409.  
  410.     int operator == (const TINode& other) const
  411.         {
  412.         return *t == *other.t;
  413.         }
  414.  
  415.     int operator < (const TINode& other) const
  416.         {
  417.         return *t < *other.t;
  418.         }
  419.  
  420. private:
  421.     T* t;
  422.  
  423.     const TINode& operator = (const TINode&);
  424.     TINode (const TINode&);
  425. };
  426. #endif
  427.